package com.morizhang.usersys.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.morizhang.usersys.api.bean.ApiDefinitionHolder;
import com.morizhang.usersys.api.bean.ErrorDefinition;
import com.morizhang.usersys.api.bean.ErrorDefinitionHolder;
import com.morizhang.usersys.api.service.ServiceAnnotation;
import com.morizhang.usersys.api.utils.RequestUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.Iterator;

public abstract class AbstractApiController implements ApplicationListener<ContextRefreshedEvent> {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractApiController.class);

    private volatile boolean isInit = false;

    @Autowired
    private Environment environment;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {

        System.out.println("!!!!!");

        if (isInit) {
            return;
        }
        ApplicationContext applicationContext = event.getApplicationContext();

        String[] beanNames = applicationContext.getBeanNamesForAnnotation(ServiceAnnotation.class);
        if (beanNames == null || beanNames.length == 0)
            return;
        LOGGER.info("开始注册服务");
        for (String beanName : beanNames) {
            LOGGER.info("正在获取类：" + beanName);
            IService service = (IService) applicationContext.getBean(beanName);
            ServiceAnnotation serviceAnnotation = AnnotationUtils.getAnnotation(service.getClass(),ServiceAnnotation.class);
            ApiDefinitionHolder.add(serviceAnnotation.name(),service);
            LOGGER.info("已成功装载服务:" + serviceAnnotation.name());
        }
        LOGGER.info("服务已注册完毕");

        LOGGER.info("开始注册错误类型");
        try {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(environment.getProperty("error.definition.location"));
            Element errorDefinitions = document.getRootElement();
            HashSet<String> warnDup = new HashSet<>();
            for (Iterator<Element> i = errorDefinitions.elementIterator(); i.hasNext();) {
                Element errorClass = i.next();
                String classCode = errorClass.attributeValue("classCode");
                String className = errorClass.attributeValue("className");
                for (Iterator<Element> j = errorClass.elementIterator(); j.hasNext();) {
                    Element error = j.next();
                    String errorCode = error.attributeValue("errorCode");
                    String errorName = error.attributeValue("errorName");
                    String errorMessage = error.attributeValue("errorMessage");
                    ErrorDefinition errorDefinition = new ErrorDefinition();
                    errorDefinition.setErrorCode(classCode + errorCode);
                    errorDefinition.setErrorClass(className);
                    errorDefinition.setErrorName(errorName);
                    errorDefinition.setErrorMessage(errorMessage);
                    if (warnDup.contains(errorName))
                        LOGGER.warn("检测到重复的错误名称：" + errorName + "; 注意：重复的错误名称中只有最后一个会生效");
                    else
                        warnDup.add(errorName);
                    ErrorDefinitionHolder.add(errorName, errorDefinition);
                    LOGGER.info("已成功注册错误类型:" + errorName);
                }
            }

        } catch (DocumentException documentException) {
            LOGGER.error("访问错误定义文件失败，错误类型未正常装载！");
        }
        LOGGER.info("错误类型已注册完毕");
    }

    protected ApiParams createApiParams(HttpServletRequest request, String requestBody){
        ApiParams apiParams = new ApiParams();
        apiParams.setMethod(request.getMethod());
        apiParams.setContentType(request.getContentType());
        apiParams.setSourceRequestBody(requestBody);
        apiParams.setClientIP(RequestUtils.getClientIP(request));
        try {
            JSONObject requestParams = JSON.parseObject(requestBody);
            apiParams.setRequestParams(requestParams);
            apiParams.setJsonConvertSuccess(true);
        } catch (Exception exception) {
            LOGGER.error("转换请求参数为JSON时发生错误",exception);
            apiParams.setJsonConvertSuccess(false);
        }
        return apiParams;
    }
}
